const NodeRSA = require('node-rsa');
let fs = require('fs');
let config = require('../config/config');
let crypto = require("crypto");
let path = require("path");
const rs = require("jsrsasign");
const rsu = require("jsrsasign-util");

const { BusiError, SysError } = require('../exception/exception');

class Rsa {
    constructor() {
    }

    async keyPairsGen() {
        let key = new NodeRSA({ b: 2048 });
        key.setOptions({ encryptionScheme: 'pkcs1' });

        let privatePem = key.exportKey('pkcs1-private-pem');
        let publicPem = key.exportKey('pkcs1-public-pem');

        fs.writeFile('./pem/public.pem', publicPem, (err) => {
            if (err) throw SysError(err);
            console.logw('公钥已保存！');
        });
        fs.writeFile('./pem/private.pem', privatePem, (err) => {
            if (err) throw SysError(err);
            console.logw('私钥已保存！');
        });
    }

    async keyPairsGen8() {
        let key = new NodeRSA({b: 2048}); //生成新的512位长度密钥
        // key.setOptions({ encryptionScheme: 'pkcs8' });
        let privatePem = key.exportKey('pkcs8-private-pem');
        let publicPem = key.exportKey('pkcs8-public-pem');


        fs.writeFile('./pem/public.pem', publicPem, (err) => {
            if (err) throw SysError(err);
            console.logw('公钥已保存！');
        });

        fs.writeFile('./pem/private.pem', privatePem, (err) => {
            if (err) throw  SysError(err);
            console.logw('私钥已保存！');
        });
    }

    async sign256(str) {
        return new Promise((resolve, reject) => {
            fs.readFile(config.conf["pay.qft.priKey"], (err, data) => {
                if (err) {
                    console.log("read rsa key public file err:", err);
                    reject(err);
                } else {
                    const sig = new rs.KJUR.crypto.Signature({"alg": "SHA256withRSA"});
                    let priKey = new Buffer(data).toString("ascii");
                    sig.init(priKey);
                    sig.updateString(str);
                    const hSigVal = sig.sign();
                    resolve(Buffer.from(hSigVal, 'hex').toString('base64'));
                }
            });
        });
    }

    async verify256(signStr, sign) {
        return new Promise((resolve, reject) => {
            fs.readFile(config.conf["pay.qft.pubKeyPlat"], (err, data) => {
                if (err) {
                    console.log("read rsa key public file err:", err);
                    reject(err);
                } else {
                    const sig = new rs.KJUR.crypto.Signature({ "alg": "SHA256withRSA" });
                    let pubKey = new Buffer(data).toString("ascii");
                    sig.init(pubKey);
                    sig.updateString(signStr);
                    let signHex = Buffer.from(sign, 'base64').toString('hex');
                    const isValid = sig.verify(signHex);
                    resolve(isValid);
                }
            });
        });
    }

    async encryptWithPriKey(encryptStr) {
        return new Promise((resolve, reject) => {
            fs.readFile(config.conf["pay.qft.priKey"], (err, data) => {
                if (err){
                    console.log("read rsa key private file err:", err);
                    reject(err);
                } else {
                    let key = new NodeRSA(data);
                    let cipherText = key.encryptPrivate(encryptStr, 'utf8');
                    console.log(cipherText);
                    resolve(cipherText);
                }
            });
        });
    }

    async decryptWithPubKey(encryptStr) {
        return new Promise((resolve, reject) => {
            fs.readFile(config.conf["pay.qft.pubKey"], (err, data) => {
                if (err){
                    console.log("read rsa key public file err:", err);
                    reject(err);
                } else {
                    let key = new NodeRSA(data);
                    let cipherText = key.decryptPublic(encryptStr, 'utf8');
                    console.log(cipherText);
                    resolve(cipherText);
                }
            });
        });
    }

    async sign1(str) {
        return new Promise((resolve, reject) => {
            fs.readFile(config.conf["pay.qft.priKey"], (err, data) => {
                if (err) {
                    console.log("read rsa key public file err:", err);
                    reject(err);
                } else {
                    const sig = new rs.KJUR.crypto.Signature({ "alg": "SHA1withRSA" });
                    let priKey = new Buffer(data).toString("ascii");
                    sig.init(priKey);
                    sig.updateString(str);
                    const hSigVal = sig.sign();
                    resolve(Buffer.from(hSigVal, 'hex').toString('base64'));
                }
            });
        });
    }

    // sign is in hex format
    verify1(signStr, sign) {
        return new Promise((resolve, reject) => {
            fs.readFile(config.conf["pay.qft.pubKeyPlat"], (err, data) => {
                if (err) {
                    console.log("read rsa key public file err:", err);
                    reject(err);
                } else {
                    const sig = new rs.KJUR.crypto.Signature({ "alg": "SHA1withRSA" });
                    let pubKey = new Buffer(data).toString("ascii");
                    sig.init(pubKey);
                    sig.updateString(signStr);
                    let signHex = Buffer.from(sign, 'base64').toString('hex');
                    const isValid = sig.verify(signHex);
                    resolve(isValid);
                }
            });
        });
    }
}

let rsa = new Rsa();
module.exports = rsa;